'''
copyright: Copyright (C) 2015-2024, Wazuh Inc.

           Created by Wazuh, Inc. <info@wazuh.com>.

           This program is free software; you can redistribute it and/or modify it under the terms of GPLv2

type: integration

brief: Wazuh is able to detect vulnerabilities in the applications installed in agents using the Vulnerability Detector
       module. This software audit is performed through the integration of vulnerability feeds indexed by Redhat,
       Canonical, Debian, Amazon Linux and NVD Database.

components:
    - vulnerability_detector

suite: feeds

targets:
    - manager

daemons:
    - wazuh-modulesd
    - wazuh-db
    - wazuh-analysisd

os_platform:
    - linux

os_version:
    - Arch Linux
    - Amazon Linux 2022
    - Amazon Linux 2
    - Amazon Linux 1
    - CentOS 8
    - CentOS 7
    - Debian Buster
    - Red Hat 8
    - Ubuntu Trusty
    - Ubuntu Xenial
    - Ubuntu Bionic
    - Ubuntu Focal
    - Ubuntu Jammy
    - SUSE Linux Enterprise Desktop 11
    - SUSE Linux Enterprise Desktop 12
    - SUSE Linux Enterprise Desktop 15
    - SUSE Linux Enterprise Server 11
    - SUSE Linux Enterprise Server 12
    - SUSE Linux Enterprise Server 15

references:
    - https://documentation.wazuh.com/current/user-manual/capabilities/vulnerability-detection/
    - https://documentation.wazuh.com/current/user-manual/capabilities/syscollector.html

tags:
    - vulnerability
    - vulnerability_detector
    - download
    - feeds
'''
import pytest
from pathlib import Path

from wazuh_testing.constants.daemons import ANALYSISD_DAEMON, MODULES_DAEMON, SYSCHECK_DAEMON
from wazuh_testing.constants.paths.logs import WAZUH_LOG_PATH
from wazuh_testing.utils.callbacks import generate_callback
from wazuh_testing.tools.monitors.file_monitor import FileMonitor
from wazuh_testing.utils.db_queries.cve_db import get_rows_from_table
from wazuh_testing.utils.configuration import get_test_cases_data, load_configuration_template
from wazuh_testing.modules.modulesd.vulnerability_detector import patterns as cb
from wazuh_testing.modules.modulesd.configuration import MODULESD_DEBUG
from wazuh_testing.modules.monitord.configuration import MONITORD_ROTATE_LOG
from . import TEST_CASES_PATH, CONFIGURATIONS_PATH


pytest.skip("The tests will be deprecated, they test the old Vulnerability Detector.", allow_module_level=True)

pytestmark = [pytest.mark.server]

# Variables
local_internal_options = {MODULESD_DEBUG: '2', MONITORD_ROTATE_LOG: '0'}
daemons_handler_configuration = {'daemons': [ANALYSISD_DAEMON, MODULES_DAEMON, SYSCHECK_DAEMON]}

# Configuration and cases data
configurations_path = Path(CONFIGURATIONS_PATH, 'configuration_msu_inventory.yaml')
cases_path = Path(TEST_CASES_PATH, 'cases_msu_inventory.yaml')

# Test configurations
configuration_parameters, configuration_metadata, case_ids = get_test_cases_data(cases_path)
configurations = load_configuration_template(configurations_path, configuration_parameters, configuration_metadata)

# Variables
# This patches are searched for to verify they are added correctly from the Catalog even if not associated to a CVE
patch_references = ['4465477', '5003711', '4470788']


@pytest.mark.tier(level=2)
@pytest.mark.parametrize('test_configuration, test_metadata', zip(configurations, configuration_metadata), ids=case_ids)
def test_msu_catalog_patches(test_configuration, test_metadata, set_wazuh_configuration, truncate_monitored_files,
                             configure_local_internal_options, clean_cve_tables, daemons_handler):
    '''
    description: Check that patch information is added to the feed from the catalog for patches not directly related
                 to a Vulnerability.

    test_phases:
        Setup:
            - Set a custom Wazuh configuration.
            - Restart wazuh-modulesd.
        Test:
            - Check in log that the database provider has been updated successfully.
            - Query the DB to check patch is found in MSU_SUPERSEDENSE table
            - Query the DB to check patch is not found in MSU table (has no Vulnerability linked to it).
        Teardown:
            - Clean the database.
            - Stop wazuh-modulesd.

    wazuh_min_version: 4.5.0

    tier: 2

    parameters:
        - test_configuration:
            type: dict
            brief: Wazuh configuration data. Needed for set_wazuh_configuration fixture.
        - test_metadata:
            type: dict
            brief: Wazuh configuration metadata
        - set_wazuh_configuration:
            type: fixture
            brief: Set the wazuh configuration according to the configuration data.
        - configure_local_internal_options:
            type: fixture
            brief: Set local_internal_options configuration.
        - truncate_monitored_files:
            type: fixture
            brief: Truncate all the log files and json alerts files before and after the test execution.
        - clean_cve_tables:
            type: fixture
            brief: Clean all the CVE tables before and after running the test.
        - daemons_handler:
            type: fixture
            brief: Restart the wazuh-modulesd daemon.

    assertions:
        - Check that the feed is downloaded successfully.
        - Check that the referenced patch is found in MSU_SUPERSEDENSE table
        - Check that the referenced patch is not foundin MSU table (has no Vulnerability linked to it).

    input_description:
        - The `configuration_msu_inventory.yaml` file provides the module configuration for this test.
        - The `cases_msu_inventory.yaml` file provides the test cases.

    expected_output:
        - r'The update of the .* feed finished successfully'
    '''
    file_monitor = FileMonitor(WAZUH_LOG_PATH)
    provider = test_metadata['provider_name']

    # Check that the feed has been updated successfully
    file_monitor.start(timeout=test_metadata['download_timeout'],
                       callback=generate_callback(regex=cb.FEED_UPDATE_FINISHED,
                                                  replacement={'provider_name': provider}))
    assert file_monitor.callback_result is not None, f"Could not find 'update of {provider} feed finished' event"

    for patch in patch_references:
        # Check that patch is present in MSU_SUPERSEDENCE table
        patch_found = get_rows_from_table(patch, 'patch', 'MSU_SUPERSEDENCE')
        assert patch_found is not None, f"The Expected data for KB{patch} was not found in MSU_SUPERSEDENCE Table"

        # Check that patch is not present in MSU table
        patch_in_table = get_rows_from_table(patch, 'patch', 'MSU')
        assert patch_in_table is None, f"Unexpected data found for KB{patch} in MSU Table"
